package com.ljh.myrpc.fault.tolerant;

import com.ljh.myrpc.Proxy.MockServiceProxy;
import com.ljh.myrpc.model.RpcRequest;
import com.ljh.myrpc.model.RpcResponse;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;

/**
 * 降级到其他服务
 */
@Slf4j
public class FailBackTolerantStrategy implements TolerantStrategy{

    @Override
    public RpcResponse doTolerant(Map<String, Object> context, Exception e) throws Exception {
        // 可自行扩展，获取降级的服务并调用
        RpcRequest rpcRequest = (RpcRequest) context.getOrDefault("rpcRequest", null);
        if(rpcRequest == null){
            log.info("FailBackTolerantStrategy", e);
            throw new Exception(e.getMessage());
        }
        log.info("降级服务-调用Mock模拟接口");
        String serviceName = rpcRequest.getServiceName();
        Class<?> serviceClass = Class.forName(serviceName);
        // 使用模拟接口
        Object mockProxt = getMockProxt(serviceClass);
        Method method = mockProxt.getClass().getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
        Object result = method.invoke(mockProxt, rpcRequest.getArgs());
        // 返回结果
        RpcResponse rpcResponse = new RpcResponse();
        rpcResponse.setData(result);
        rpcResponse.setDataType(method.getReturnType());
        rpcResponse.setMessage("Fail Back Tolerant Strategy");
        return rpcResponse;
    }

    private static <T> T getMockProxt(Class<T> serviceClass){
        return (T) Proxy.newProxyInstance(
                serviceClass.getClassLoader(),
                new Class[]{serviceClass},
                new MockServiceProxy()
        );
    }

}
